package com.handydata.antifraud.channel.outbound;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import javax.annotation.Resource;

import com.handydata.antifraud.common.task.LoadPmmlRun;
import com.handydata.antifraud.common.task.UruleCheckRun;
import com.handydata.antifraud.dao.RiskRuleDictlinfoBasedataDao;
import com.handydata.antifraud.entity.RuleInfoDo;
import com.handydata.antifraud.ws.EncryInfo;
import com.handydata.common.util.RedisKey;
import com.handydata.common.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang.StringUtils;
import org.dmg.pmml.PMML;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.handydata.antifraud.rule.RuleEngineInvokerFactory;
import com.handydata.antifraud.rule.RuleEngineScheduler;
import com.rabbitmq.client.Channel;

@Slf4j
@Component
public class RabbitRuleReceiver {


    @Autowired
    private RuleEngineInvokerFactory ruleEngineInvokerFactory;

    @Resource
    private RuleEngineScheduler scheduler;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private EncryInfo encryInfo;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RiskRuleDictlinfoBasedataDao riskRuleDictlinfoBasedataDao;


    @RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "${spring.rabbitmq.queue}",
                durable="true"),
        exchange = @Exchange(value = "rule-exchange-1",
                durable="true",
                type= "fanout",
                ignoreDeclarationExceptions = "true")
    )
    )

    @RabbitHandler
    public void onMessage(Message<?> message, Channel channel) throws Exception {
        log.info("规则引擎更新消息开始执行--------------------------------------getChannelNumber {} consumer hash {}",channel.getChannelNumber(),this.hashCode());//重试机制，业务完成，消息失败也会重搞
        Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
        try{
            String msg = (String)message.getPayload();
            if(StringUtils.isEmpty(msg)) {
                channel.basicAck(deliveryTag, false);
                log.info("规则引擎消息更新，package为空，没有更新",channel.getChannelNumber(),this.hashCode());//重试机制，业务完成，消息失败也会重搞
                return;
            }
            if(msg.indexOf("model")!=-1){
                Future<PMML> futureLoadPmmlRun = this.threadPoolTaskExecutor.submit(new LoadPmmlRun(encryInfo));
                futureLoadPmmlRun.get();
            }else if(msg.indexOf("ruleType")!=-1){
                Future<Map<String, List<RuleInfoDo>>> uruleCheckMap = this.threadPoolTaskExecutor.submit(new UruleCheckRun(ruleEngineInvokerFactory, riskRuleDictlinfoBasedataDao, encryInfo));
                Map<String, List<RuleInfoDo>> ruleInfoDoMap = uruleCheckMap.get();
                if(redisUtil.set(RedisKey.RULE_KNOWLEDGE,ruleInfoDoMap)){
                    log.info("规则匹配校验成功!");
                }else{
                    throw new Exception("规则匹配校验失败放入缓存失败,重启服务。");
                }
            }else {
                msg=msg.replace("-antifraud_package.json","/antifraud_package");
                List<String> list=new ArrayList<>();
                list.add(msg);
                ruleEngineInvokerFactory.refreshRulePackage(list);
            }
            log.info("规则决策引擎包加载完成......................");
            channel.basicAck(deliveryTag, false);
        }catch (Exception ex){
            channel.basicAck(deliveryTag, false);
            log.error("转换数据出错:{}，应该是垃圾消息"+ex.getMessage(),message.getPayload());
        }

    }
}